/**
 * 
 */
package pers.vic.elasticsearch.helper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.rest.RestStatus;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import pers.vic.elasticsearch.autoconfigure.IndexConfig;
import pers.vic.elasticsearch.autoconfigure.IndexConfig.IndexProperty;

/**
 * @description: 关于ES 的Index的工具类
 * @author Vic.xu
 * @date: 2020年9月10日下午7:51:43
 */

public class IndexHelper {

	private RestHighLevelClient restHighLevelClient;

	public IndexHelper() {

	}

	public IndexHelper(RestHighLevelClient restHighLevelClient) {
		this.restHighLevelClient = restHighLevelClient;
	}

	/**
	 * 删除索引
	 * 
	 * @param index
	 * @return
	 * @throws IOException
	 */
	public boolean deleteIndex(String index) throws IOException {
		try {
			DeleteIndexRequest request = new DeleteIndexRequest(index);
			AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);

			return response.isAcknowledged();
		} catch (ElasticsearchException exception) {
			if (exception.status() == RestStatus.NOT_FOUND) {
				// throw new commonrun("Not found index: " + index);
			}
			throw exception;
		}
	}

	/**
	 * 判断索引是否 存在
	 *
	 * @param index 索引名称
	 * @return
	 * @throws IOException
	 */
	public boolean isExistIndex(String index) throws IOException {
		GetIndexRequest getIndexRequest = new GetIndexRequest(index);
		getIndexRequest.local(false);
		getIndexRequest.humanReadable(true);
		getIndexRequest.includeDefaults(false);
		return restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
	}

	/**
	 * 创建索引
	 *
	 * @param index      索引名称
	 * @param properties mappings中的属性
	 * @return
	 * @throws IOException
	 */
	public boolean createIndex(IndexConfig config) throws IOException {
		XContentBuilder builder = XContentFactory.jsonBuilder();
		builder.startObject().startObject("mappings")
				.field("properties", buildIndexProperties(config.getProperties())).endObject()
				.startObject("settings").field("number_of_shards", config.getShards())
				.field("number_of_replicas", config.getReplicas())
				// 设置默认的分词器
				.field("index.analysis.analyzer.default.type", config.getAnalyzer()).endObject().endObject();
		CreateIndexRequest request = new CreateIndexRequest(config.getName()).source(builder);

		//别名
		String alias = StringUtils.isEmpty(config.getAlias()) ? config.getName() + "_alias" : config.getAlias();
		request.alias(new Alias(alias));
		CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
		boolean acknowledged = response.isAcknowledged();
		Assert.isTrue(acknowledged, "创建Index[" + config.getName()+"]失败");
		return acknowledged;
	}

	/**
	 * 构建索引的配置属性
	 * @param list  IndexProperty 集合
	 * @return mapping
	 */
	public static Map<String, Map<String, Object>> buildIndexProperties(List<IndexProperty> list) {
		Map<String, Map<String, Object>> properties = new HashMap<>();

		// 加一个默认的 ： id 主要用来排序 因为它是自增的 还有关联mysql的数据 如果配置了 会覆盖此默认配置
		putSubProperties(properties, "id", "keyword");

		Optional.ofNullable(list).orElse(new ArrayList<IndexProperty>())
				.forEach(p -> putSubProperties(properties, p.getField(), p.getType()));

		return properties;
	}

	/**
	 * 查询子字段配置
	 * 
	 * @param properties
	 * @param field      字段名
	 * @param type       text类型
	 * @return
	 */
	public static Map<String, Object> putSubProperties(Map<String, Map<String, Object>> properties, String field,
			String type) {
		Map<String, Object> subProperties = new HashMap<>();
		subProperties.put("type", type);
		properties.put(field, subProperties);
		return subProperties;
	}

}
